using System;
using System.Collections.Generic;

namespace Framework.Event
{
    public class EventContainer : IDisposable
    {
        private string mEventKey = string.Empty;
        private LinkedList<EventUtil> mEventUtilLinkedList = new LinkedList<EventUtil>();

        public EventContainer(string pEventKey)
        {
            if (string.IsNullOrEmpty(pEventKey))
                throw new ArgumentException("Event key cannot be null or empty", nameof(pEventKey));

            this.mEventKey = pEventKey;
        }

        /// <summary>事件数量</summary>
        public int Count => mEventUtilLinkedList.Count;

        /// <summary>获取事件链表</summary>
        /// <returns></returns>
        public LinkedList<EventUtil> GetEventUtilLinkedList()
        {
            return mEventUtilLinkedList;
        }

        /// <summary>添加事件</summary>
        /// <param name="pEventKey">事件Key</param>
        /// <param name="pEventHandler"></param>
        /// <param name="pPriority">优先级</param>
        public void Add(string pEventKey, EventHandler pEventHandler, EnEventPriority pPriority = EnEventPriority.Medium)
        {
            if (string.IsNullOrEmpty(pEventKey))
                throw new ArgumentException("Event key cannot be null or empty", nameof(pEventKey));

            if (pEventHandler == null)
                throw new ArgumentNullException(nameof(pEventHandler));

            if (Contains(pEventHandler))
                throw new InvalidOperationException($"Event handler already registered for key: {pEventKey}");

            EventUtil newEventUtil = new EventUtil(pEventKey, pEventHandler, pPriority);

            if (mEventUtilLinkedList.Count <= 0)
            {
                mEventUtilLinkedList.AddFirst(newEventUtil);
                return;
            }

            LinkedListNode<EventUtil> currentNode = mEventUtilLinkedList.First;
            while (currentNode != null)
            {
                if (newEventUtil.Priority < currentNode.Value.Priority)
                {
                    mEventUtilLinkedList.AddBefore(currentNode, newEventUtil);
                    return;
                }

                currentNode = currentNode.Next;
            }

            mEventUtilLinkedList.AddLast(newEventUtil);
        }

        /// <summary>移除事件</summary>
        /// <param name="pEventHandler"></param>
        /// <returns>是否移除成功</returns>
        public bool Remove(EventHandler pEventHandler)
        {
            if (pEventHandler == null) return false;

            LinkedListNode<EventUtil> currentNode = mEventUtilLinkedList.First;
            while (currentNode != null)
            {
                LinkedListNode<EventUtil> nextNode = currentNode.Next;

                if (currentNode.Value.EventHandler == pEventHandler)
                {
                    currentNode.Value.Dispose();
                    mEventUtilLinkedList.Remove(currentNode);
                    return true;
                }

                currentNode = nextNode;
            }
            return false;
        }

        /// <summary>是否包含</summary>
        /// <param name="pEventHandler"></param>
        /// <returns>是否包含</returns>
        public bool Contains(EventHandler pEventHandler)
        {
            if (pEventHandler == null) return false;

            LinkedListNode<EventUtil> currentNode = mEventUtilLinkedList.First;
            while (currentNode != null)
            {
                if (currentNode.Value.EventHandler == pEventHandler)
                    return true;

                currentNode = currentNode.Next;
            }

            return false;
        }

        /// <summary>清除事件链表</summary>
        public void Clear()
        {
            LinkedListNode<EventUtil> currentNode = mEventUtilLinkedList.First;
            while (currentNode != null)
            {
                LinkedListNode<EventUtil> nextNode = currentNode.Next;
                currentNode.Value.Dispose();
                currentNode = nextNode;
            }

            mEventUtilLinkedList.Clear();
        }

        /// <summary>销毁处理</summary>
        public void Dispose()
        {
            Clear();
        }
    }
}